【祝!】ECSへの機密情報受け渡しがCloudFormationに対応しました!
先日、みんな大好きCloudFormationに、ECSタスク定義において待望のアップデートがやってきました!
端的にいうと、ECSのタスク定義で機密情報をSecrets ManagerやParameter Storeをキー指定で取得する方法が、今まではJSONやWebコンソールのみ設定可能だったのが、CloudFormationでも設定可能となったというものです。
AWS::ECS::TaskDefinition In the ContainerDefinition property type, use the ResourceRequirements property to specify the type and amount of a resource to assign to a container. The only supported resource is a GPU.
In the ContainerDefinition property type, use the Secrets property to specify the secrets to pass to the container.
Use the Tags property to apply metadata to task definitions to help you categorize and organize them.
頻出機能なのに、CloudFormationだけで設定できなかった悲しみが一気に解消される素晴らしいアップデートなので、みなさんも試してみましょう!
CFnでECS秘密情報きたか…!! ( ゚д゚) ガタッ / ヾ __L| / ̄ ̄ ̄/_ \/ /
CloudFormation対応してなかった時代の悲しみ
2018年12月、下記ブログで書いたように、ECSのタスク定義に対して機密情報をSecretsManagerやParameter Storeから直接指定できる、めちゃくちゃ便利なアップデートがリリースされました。
- ECSでごっつ簡単に機密情報を環境変数に展開できるようになりました! | DevelopersIO
- 【祝!】FargateでもECSにごっつ簡単に環境変数に機密情報を渡せるようになりました! | DevelopersIO
しかし、これらの設定方法に対応していたのは、以下の2点だけで、CloudFormationには対応していなかったのです。
- Webコンソール
- ECSのタスク定義画面
- AWS CLIの
register-task-definition
- register-task-definition — AWS CLI 1.16.179 Command Reference
AWSで新しい機能(API)がリリースされたとき、CloudFormationのプロパティが後からの対応となることは多くあります。その間はじっと我慢の子なのですが、今回は約半年の時を超えての対応となりました。
今までは、ECSのクラスターやサービスをCloudFormationで定義しても、タスク定義はAWS CLIからJSONで更新、という使い分けが必須だったのが、タスク定義含めてCloudFormationで完結する利点は大きいです。
ECSコンテナ定義のCloudFormationの変更内容
具体的には、ECSのTaskDefinition
内のContainerDefinition
においてSecrets
が、新しくサポートされています。
Secrets
の定義はこちら。
YAMLの定義は、以下の通り。
Name: String ValueFrom: String
- Name
- コンテナ内で利用する環境変数名を指定
- ValueFrom
- コンテナ内に埋め込む機密情報を指定サポートしているのは、以下の2種
- Secrets ManagerのフルARN
- Parameter StoreセキュアストリングのフルARN(もしくは、同じリージョンにParameter Storeが存在するなら、そのキー名)
以前から、JSONで登録していた人にはおなじみのプロパティですね。Webコンソールで登録していた人には、環境変数のEnvironment
ではないことに、注意が必要です。
環境変数確認用コンテナの準備
最初に、Webアクセスで環境変数を表示するコンテナを用意します。
環境変数確認用コンテナの用意
Fargateでは、コンテナにSSHログインできないので、以下のPHPコンテナを用意します。
<?php phpinfo(); ?>
FROM php:7-apache COPY phpinfo.php /var/www/html
上記コンテナは、DockerHubにアップ済みです。
環境変数確認用コンテナの動作確認
適当なdockerクライアントで、動作確認用コンテナを起動してみてください。以下のコマンドではローカルホストのポート8080でリクエストを待ちます。
docker container run -it -p 8080:80 hamako9999/list-environments-php-container:latest
コンテナ起動後、http://localhost:8080/phpinfo.php
にアクセスして、こんな感じのphpinfoの結果が表示されればOKです。
CloudFormationによる機密情報のタスク定義への読込
それでは、実際にCloudFormationを使って、コンテナ定義に機密情報を登録してみます。
Parameter Storeへのシークレット情報の登録
シークレット情報の登録は、以下のブログの記事を参考に実施してください。
ECSでごっつ簡単に機密情報を環境変数に展開できるようになりました! | DevelopersIO
- パラメータストアーへの、秘密情報登録
CloudFormationによるタスク定義
いよいよ、CloudFormationでタスク定義を登録します。以下のCloudFormationテンプレートファイルを用意します。
AWSTemplateFormatVersion: '2010-09-09' Description: ecs task definition Resources: # ------------------------------------------------------------# # Role # ------------------------------------------------------------# ecsTaskExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Principal: Service: - "ecs-tasks.amazonaws.com" Action: - "sts:AssumeRole" ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy - arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess - arn:aws:iam::aws:policy/SecretsManagerReadWrite # ------------------------------------------------------------# # TaskDefinition # ------------------------------------------------------------# Taskdefinition: Type: AWS::ECS::TaskDefinition DependsOn: ecsTaskExecutionRole Properties: Family: cfn-secrets-sample RequiresCompatibilities: - FARGATE Cpu: 256 Memory: 512 NetworkMode: awsvpc ExecutionRoleArn: !GetAtt ecsTaskExecutionRole.Arn TaskRoleArn: !GetAtt ecsTaskExecutionRole.Arn ContainerDefinitions: - Name: cfn-secrets-sample-container Image: hamako9999/list-environments-php-container:latest PortMappings: - ContainerPort: 80 Secrets: - Name: HAMADA_SECRETS ValueFrom: hamako-favorite-word
以下、テンプレートの解説です。
アクセスポリシー付与
- arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess - arn:aws:iam::aws:policy/SecretsManagerReadWrite
ECSのタスク実行ロールに対して、Parameter StoreとSecrets Managerへのアクセスポリシーを付与します。
DockerHubイメージへのリンク指定
Image: hamako9999/list-environments-php-container:latest
自分がDockerHubにあげている、環境変数をWeb画面から確認するためのイメージへのURLを指定。
機密情報の取得設定
今回のアップデートの一番重要な部分。環境変数名とParameter Storeに登録した機密情報のパスをセットします。
Secrets: - Name: HAMADA_SECRETS ValueFrom: hamako-favorite-word
aws cliを最新バージョンに更新しておきます(以下は、2019年6月17日時点)。
$ aws --version aws-cli/1.16.179 Python/3.6.4 Darwin/18.5.0 botocore/1.12.169
上記テンプレートファイルが用意できたら、aws cliよりテンプレートを実行しCloudFormationのスタックを作成します。もちろん、Webコンソールから実行してもOkです。
$ aws cloudformation deploy --stack-name cfn-sample-secrets --template-file crn-sample-secrets.yml \ --capabilities CAPABILITY_NAMED_IAM Waiting for changeset to be created.. Waiting for stack create/update to complete Successfully created/updated stack - cfn-sample-secrets
無事、スタックが作成されましたでしょうか?
ECSコンソールからタスク定義を確認し、タスク定義cfn-secrets-sample
が作成されていればOKです。
定義をJSONで表示し、secrets
が設定されていれば、成功やで!
登録したECSタスクを実行して動作確認
後は、タスクを実行して動作確認します。テンポラリで動かすタスクであれば、ECSサービスを作らなくても、タスク定義の画面から、「アクション」→「タスクの実行」が早いです。
タスクの実行画面で、適当なパブリックサブネットにタスクを配置し、セキュリティグループを設定して、パブリックIPを付与します(詳細は環境によって適宜変更ください)。
無事、正常にタスクが実行したら、タスクに付与されたパブリックIPを利用して、https://[public-ip]/phpinfo.php
にアクセスしてみてください。無事、環境変数HAMADA_SECRETS
に、やんごとなき機密情報wassyoi
が登録されていることが確認できたでしょうか。お疲れ様でした!
CloudFormationだけでECS周辺を管理できる嬉しみを貴方に
コンテナアプリケーションにおいて、DBアクセスするためのパスワードや、他のWebサービスへの接続用APIトークンなどの機密情報の扱いは、ほぼ必須の要件です。
ECSへの機密情報受け渡しがマネージドサービスでできるようになったことは非常に大きな喜びでしたが、CloudFormationでECS周辺の各リソースを定義していた現場においては、その必須要件がCloudFormationに対応していないのは、大きなストレスでした。
今回のアップデートで、機密情報のマネージドサービス(Parameter Storeや、Secrets Manager)からコンテナへの受け渡しも設定できることで、より一貫したCloudFormationによるインフラ管理が実現できるってもんです。素晴らしい!
待ってましたよ!この機能!みんなも現場でどんどん使っていきましょう!
それでは、今日はこのへんで。濱田(@hamako9999)でした。